package util

import (
	"math"
)

func SafeToUint32(src int32) uint32 {
	if int64(src) > int64(math.MaxUint32) {
		return math.MaxUint32
	} else if src < 0 {
		return 0
	}
	return uint32(src)
}
func SafeToInt16(src int32) int16 {
	if src > math.MaxInt16 {
		return math.MaxInt16
	} else if src < math.MinInt16 {
		return math.MinInt16
	}
	return int16(src)
}
func SafeToUint16(src int32) uint16 {
	if src > math.MaxUint16 {
		return math.MaxUint16
	} else if src < 0 {
		return 0
	}
	return uint16(src)
}
func SafeAddInt32(src int32, add int32) int32 {
	return int32(Int64Range(int64(src)+int64(add), 0, math.MaxInt32))
}
func SafeAddUint32(src uint32, add int32) uint32 {
	return uint32(Int64Range(int64(src)+int64(add), 0, math.MaxUint32))
}
func SafeAddUint16(src uint16, add int32) uint16 {
	return uint16(Int32Range(int32(src)+add, 0, math.MaxUint16))
}
func SafeAddUint8(src uint8, add int32) uint8 {
	return uint8(Int32Range(int32(src)+add, 0, math.MaxUint8))
}
func SafeToUint8(src int32) uint8 {
	if src > math.MaxUint8 {
		return math.MaxUint8
	} else if src < 0 {
		return 0
	}
	return uint8(src)
}
func SafeToInt8(src int32) int8 {
	if src > math.MaxInt8 {
		return math.MaxInt8
	} else if src < math.MinInt8 {
		return math.MinInt8
	}
	return int8(src)
}

func FRound(a float32) int32 {
	if a < 0 {
		return -1 * int32(-a+0.5)
	} else {
		return int32(a + 0.5)
	}
}

func Int8Max(a int8, b int8) int8 {
	if a > b {
		return a
	} else {
		return b
	}
}
func Int8Min(a int8, b int8) int8 {
	if a < b {
		return a
	} else {
		return b
	}
}
func Int8Range(val int8, min int8, max int8) int8 {
	return Int8Min(Int8Max(val, min), max)
}
func UInt8Max(a uint8, b uint8) uint8 {
	if a > b {
		return a
	} else {
		return b
	}
}
func UInt8Min(a uint8, b uint8) uint8 {
	if a < b {
		return a
	} else {
		return b
	}
}
func UInt8Range(val uint8, min uint8, max uint8) uint8 {
	return UInt8Min(UInt8Max(val, min), max)
}
func Int16Max(a int16, b int16) int16 {
	if a > b {
		return a
	} else {
		return b
	}
}
func Int16Min(a int16, b int16) int16 {
	if a < b {
		return a
	} else {
		return b
	}
}
func UInt16Max(a uint16, b uint16) uint16 {
	if a > b {
		return a
	} else {
		return b
	}
}
func UInt16Min(a uint16, b uint16) uint16 {
	if a < b {
		return a
	} else {
		return b
	}
}
func Int32Max(a int32, b int32) int32 {
	if a > b {
		return a
	} else {
		return b
	}
}
func Int32Min(a int32, b int32) int32 {
	if a < b {
		return a
	} else {
		return b
	}
}
func Int32Range(val int32, min int32, max int32) int32 {
	return Int32Min(Int32Max(val, min), max)
}
func Int64Max(a int64, b int64) int64 {
	if a > b {
		return a
	} else {
		return b
	}
}
func Int64Min(a int64, b int64) int64 {
	if a < b {
		return a
	} else {
		return b
	}
}
func Int64Range(val int64, min int64, max int64) int64 {
	return Int64Min(Int64Max(val, min), max)
}
func IntMax(a int, b int) int {
	if a > b {
		return a
	} else {
		return b
	}
}
func IntMin(a int, b int) int {
	if a < b {
		return a
	} else {
		return b
	}
}

func Float32Max(a float32, b float32) float32 {
	if a > b {
		return a
	} else {
		return b
	}
}
func Float32Min(a float32, b float32) float32 {
	if a < b {
		return a
	} else {
		return b
	}
}
func Float32Range(val float32, min float32, max float32) float32 {
	return Float32Min(Float32Max(val, min), max)
}

func GetPairsIntList(ints IntList, proc func(a int32, b int32)) {
	if proc == nil {
		return
	}

	intLen := int(ints.GetLen())
	if intLen <= 1 {
		return
	}
	for i := 0; i < intLen; i++ {
		for k := i + 1; k < intLen; k++ {
			ia := ints.GetInt(i)
			ib := ints.GetInt(k)
			if ia != ib {
				proc(ia, ib)
			}
		}
	}
}

func IsIntListAllZero(ints IntList) bool {
	for i := 0; i < int(ints.GetLen()); i++ {
		if ints.GetInt(i) != 0 {
			return false
		}
	}
	return true
}

func RemoveDupInIntList(ints []int64) (rlt []int64) {
	intsMap := map[int64]byte{}
	for i := 0; i < len(ints); i++ {
		intsMap[ints[i]] = 1
	}
	for n := range intsMap {
		rlt = append(rlt, n)
	}
	return
}
func RemoveDupInShortIntList(ints []int64) (rlt []int64) {
	for i := 0; i < len(ints); i++ {
		isDup := false
		for j := 0; j < i; j++ {
			if ints[i] == ints[j] {
				isDup = true
				break
			}
		}
		if !isDup {
			rlt = append(rlt, ints[i])
		}
	}
	return
}
func RemoveDupInShortInt32List(ints []int32) (rlt []int32) {
	for i := 0; i < len(ints); i++ {
		isDup := false
		for j := 0; j < i; j++ {
			if ints[i] == ints[j] {
				isDup = true
				break
			}
		}
		if !isDup {
			rlt = append(rlt, ints[i])
		}
	}
	return
}

func BoolToInt(b bool) int {
	if b {
		return 1
	} else {
		return 0
	}
}

func CalculateStandardDeviationInt(ints []int) float64 {
	if len(ints) <= 0 {
		return 0
	}

	sum := 0
	for _, n := range ints {
		sum += n
	}
	mean := float64(sum) / float64(len(ints))

	sum2 := float64(0)
	for _, n := range ints {
		dt := float64(n) - mean
		sum2 += dt * dt
	}

	return math.Sqrt(sum2 / float64(len(ints)))
}
